package com.fh.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fh.mapper.ProductImgMapper;
import com.fh.mapper.ProductMapper;
import com.fh.mapper.ProductSkuMapper;
import com.fh.model.*;
import com.fh.model.es.ProductEs;
import com.fh.model.vo.ProductVO;
import com.fh.service.ProductService;
import com.fh.utils.PageHelper;
import com.fh.utils.ResultState;
import com.fh.vo.ResultVo;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.data.elasticsearch.annotations.Highlight;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.*;

@Service
public class ProductServiceImpl implements ProductService {

 @Resource
    private ProductMapper productMapper;

 @Resource
    private ProductImgMapper productImgMapper;

 @Resource
 private ProductSkuMapper productSkuMapper;

    @Resource
    private ObjectMapper objectMapper=new ObjectMapper();
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private RestHighLevelClient restHighLevelClient;


    @Override
    public ResultVo selectProductVO() {

        List<ProductVO> productVOS = productMapper.selectProductVO();

        return new ResultVo(ResultState.OK,"ok",productVOS);
    }

    @Override
    public ResultVo getProductDetailsInfo(String productId) {

        try {
            String products = (String) stringRedisTemplate.boundHashOps("products").get(productId);
            if (products!=null){
                Product product = objectMapper.readValue(products, Product.class);

                String productImgs = (String) stringRedisTemplate.boundHashOps("productImgs").get(productId);
                JavaType javaType1 = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, ProductImg.class);
                List<ProductImg> productImg= objectMapper.readValue(productImgs, javaType1);

                String productSku = (String) stringRedisTemplate.boundHashOps("productSkus").get(productId);
                JavaType javaType2 = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, ProductSku.class);
                List<ProductSku> productSkus = objectMapper.readValue(productSku, javaType2);
                Map<String,Object> map=new HashMap<>();
                map.put("products",product);
                map.put("productImgs",productImg);
                map.put("productSkus",productSkus);
                return new ResultVo(ResultState.OK,"ok",map);
            }else {
                Example example = new Example(Product.class);
                Example.Criteria criteria = example.createCriteria();
                criteria.andEqualTo("productId",productId);
                criteria.andEqualTo("productStatus",1);
                Product product = productMapper.selectOneByExample(example);
                stringRedisTemplate.boundHashOps("products").put(productId,objectMapper.writeValueAsString(product));
                if (product!=null){
                    stringRedisTemplate.boundHashOps("products").put(productId,objectMapper.writeValueAsString(product));


                    Example example2 = new Example(ProductImg.class);
                    Example.Criteria criteria2 = example2.createCriteria();
                    criteria2.andEqualTo("itemId",productId);
                    List<ProductImg> productImgs = productImgMapper.selectByExample(example2);
                    stringRedisTemplate.boundHashOps("productImgs").put(productId,objectMapper.writeValueAsString(productImgs));


                    Example example3 = new Example(ProductSku.class);
                    Example.Criteria criteria3 = example3.createCriteria();
                    criteria3.andEqualTo("productId",productId);
                    criteria3.andEqualTo("status",1);
                    List<ProductSku> productSkus = productSkuMapper.selectByExample(example3);
                    stringRedisTemplate.boundHashOps("productSkus").put(productId,objectMapper.writeValueAsString(productSkus));


                    Map<String,Object> map=new HashMap<>();
                    map.put("products",product);
                    map.put("productImgs",productImgs);
                    map.put("productSkus",productSkus);
                    return new ResultVo(ResultState.OK,"ok",map);
                }else {
                    return new ResultVo(ResultState.NO,"ok",null);
                }
            }
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }


    public  ResultVo searchProduct(String keyWord , int pageNum,int limit){
       //执行检索
        try {
            //从es中查询搜索结果
            SearchRequest searchRequest=new SearchRequest("fengmi");
            SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
            //查询条件
            searchSourceBuilder.query(QueryBuilders.matchQuery("productName",keyWord));
            //分页条件
            int start=(pageNum-1)*limit;
            searchSourceBuilder.from(start);
            searchSourceBuilder.size(limit);
            //高亮显示
            HighlightBuilder highlightBuilder=new HighlightBuilder();
            HighlightBuilder.Field field=new HighlightBuilder.Field("productName");
            highlightBuilder.field(field);
            highlightBuilder.preTags("<label style='color:red'>");
            highlightBuilder.postTags("</label>");
            searchSourceBuilder.highlighter(highlightBuilder);
            searchRequest.source(searchSourceBuilder);

            //执行检索
            SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            //封装结果
            SearchHits hits = search.getHits();
            //获取总条数
            int count= (int) hits.getTotalHits().value;
            //计算总页数
            int pageCount=count%limit==0?count/limit:count/limit+1;

            List<ProductEs> list=new ArrayList<>();
            Iterator<SearchHit> iterator = hits.iterator();

           while (iterator.hasNext()){
               SearchHit searchHit = iterator.next();
               ProductEs productEs = objectMapper.readValue(searchHit.getSourceAsString(), ProductEs.class);
            //获取高亮字段
               Map<String, HighlightField> highlightFieldMap=searchHit.getHighlightFields();
               HighlightField highlightField=highlightFieldMap.get("productName");
               String s = Arrays.toString(highlightField.fragments());
               productEs.setProductName(s);
               list.add(productEs);
           }

           //封装分页数据
            PageHelper<ProductEs> pageHelper=new PageHelper(count,pageCount,list);

            return new ResultVo(ResultState.OK,"ok",pageHelper);
        } catch (IOException e) {
            e.printStackTrace();
            return new ResultVo(ResultState.NO,"no",null);
        }


    }



}
